package br.com.framework.persistencia.api;

import java.util.List;
import java.util.Map;

import javax.persistence.PersistenceException;

import br.com.framework.persistencia.model.BaseEntity;
import br.com.framework.persistencia.sort.Order;

/**
 * Interface no padrão DAO (Data Access Object) que permite manipular os dados de uma entidade.
 * 
 * @author Cleber Moura
 *
 * @param <ID> representa o tipo do identificador da entidade.
 * @param <E> representa o tipo da entidade.
 */
public interface BaseDao<E extends BaseEntity> {

	/**
	 * Busca uma entidade pelo Id
	 * @param id
	 * @return
	 * @throws PersistenceException
	 */
	E getByID(Long id) throws PersistenceException;
	
	/**
	 * Busca todos os registros ativos.
	 * @return
	 * @throws PersistenceException
	 */
	List<E> findAll() throws PersistenceException;
	
	/**
	 * Busca todos os registros.
	 * 
	 * @param onlyActive
	 * 	true - o resultado conterá apenas os registros ativos; <br/>
	 *  false - o resultado conterá todos os registros, ativos e inativos; 
	 * @return
	 * @throws PersistenceException
	 */
	List<E> findAll(boolean onlyActive) throws PersistenceException;
	
	/**
	 * Busca todos os registros ativos de forma paginada.
	 * 
	 * @param firstResult
	 * @param maxResults
	 * @return
	 * @throws PersistenceException
	 */
	List<E> findAll(int firstResult, int maxResults) throws PersistenceException;
	
	/**
	 * Busca todos os registros de forma paginada.
	 * 
	 * @param firstResult
	 * @param maxResults
	 * @param onlyActive
	 * 	true - o resultado conterá apenas os registros ativos; <br/>
	 *  false - o resultado conterá todos os registros, ativos e inativos;
	 * @return
	 * @throws PersistenceException
	 */
	public List<E> findAll(int firstResult, int maxResults, boolean onlyActive) throws PersistenceException;
	
	/**
	 * Busca todos os registros de forma paginada e ordenada.
	 * 
	 * @param firstResult
	 * @param maxResults
	 * @param sortField
	 * @param sortOrder
	 * @param onlyActive
	 * 	true - o resultado conterá apenas os registros ativos; <br/>
	 *  false - o resultado conterá todos os registros, ativos e inativos;
	 * @return
	 * @throws PersistenceException
	 */
	public List<E> findAll(int firstResult, int maxResults, String sortField, Order sortOrder, boolean onlyActive) throws PersistenceException;
	
	/**
	 * Busca todos os registros de forma ordenada.
	 * 
	 * @param sortField
	 * @param sortOrder
	 * @param onlyActive
	 * 	true - o resultado conterá apenas os registros ativos; <br/>
	 *  false - o resultado conterá todos os registros, ativos e inativos;
	 * @return
	 * @throws PersistenceException
	 */
	public List<E> findAll(String sortField, Order sortOrder, boolean onlyActive) throws PersistenceException;
	
	/**
	 * Busca todos os registros de forma paginada, filtrada e ordenada.
	 * 
	 * @param firstResult
	 * @param maxResults
	 * @param sortField
	 * @param sortOrder
	 * @param filters
	 * 	Map<String, String> Representando atributo/valor para a filtragem.
	 * @param onlyActive
	 * 	true - o resultado conterá apenas os registros ativos; <br/>
	 *  false - o resultado conterá todos os registros, ativos e inativos;
	 * @return
	 * @throws PersistenceException
	 */
	public List<E> findAll(int firstResult, int maxResults, String sortField, Order sortOrder, Map<String, String> filters, boolean onlyActive) throws PersistenceException;
	
	/**
	 * @param entidade
	 * @return
	 * @throws PersistenceException
	 */
	void insert(E entidade) throws PersistenceException;
	
	/**
	 * Modifica os dados da entidade no banco de dados.
	 *  
	 * @param entidade
	 * @return
	 * @throws PersistenceException
	 */
	void update(E entidade) throws PersistenceException;
	
	/**
	 * Recarrega os dados da entidade do banco de dados.
	 *  
	 * @param entidade
	 * @return
	 * @throws PersistenceException
	 */
	void refresh(E entidade) throws PersistenceException;
	
	/**
	 * Efetrua a remoção lógica de um registro.
	 * 
	 * @param entidade
	 * @throws PersistenceException
	 */
	void remove(E entidade) throws PersistenceException;
	
	/**
	 * Efetua a remoçao de um registro. 
	 * Se o parametro 'removerLogicamente' for true, a remoção será apenas lógica.
	 * Se for false, será feita a remoção física do banco de dados.
	 * 
	 * @param entidade
	 * @param removerLogicamente
	 * @throws PersistenceException
	 */
	void remove(E entidade, boolean removerLogicamente) throws PersistenceException;
	
	/**
	 * Efetrua a remoção lógica de um registro pelo ID.
	 * 
	 * @param id
	 * @throws PersistenceException
	 */
	void remove(Long id) throws PersistenceException;
	
	/**
	 * Efetua a remoçao de um registro pelo ID
	 * Se o parametro 'isLogicalDelete' for true, a remoção será apenas lógica.
	 * Se for false, será feita a remoção física do banco de dados.
	 * 
	 * @param entidade
	 * @param isLogicalDelete
	 * @throws PersistenceException
	 */
	void remove(Long id, boolean isLogicalDelete) throws PersistenceException;
	
	/**
	 * Retorna o total de registros ativos.
	 * 
	 * @return
	 * @throws PersistenceException
	 */
	public Long getRecordCount() throws PersistenceException;
	
	/**
	 * Retorna o total de registros.
	 * 
	 * @param onlyActive
	 * 	true - o resultado conterá apenas os registros ativos; <br/>
	 *  false - o resultado conterá todos os registros, ativos e inativos;
	 * @return
	 * @throws PersistenceException
	 */
	public Long getRecordCount(boolean onlyActive) throws PersistenceException;
	
	/**
	 * Retorna o total de registros.
	 * 
	 * @param filters
	 * 	Map<String, String> Representando atributo/valor para a filtragem.
	 * @param onlyActive
	 * 	true - o resultado conterá apenas os registros ativos; <br/>
	 *  false - o resultado conterá todos os registros, ativos e inativos;
	 * @return
	 * @throws PersistenceException
	 */
	public Long getRecordCount(Map<String, String> filters, boolean onlyActive) throws PersistenceException;
}
